/* * Copyright (C) 2021 Huawei Device Co., Ltd.
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.zchu.sample.slice;

import com.google.gson.reflect.TypeToken;
import com.zchu.rxcache.RxCache;
import com.zchu.rxcache.data.CacheResult;
import com.zchu.rxcache.data.ResultFrom;

import com.zchu.rxcache.diskconverter.GsonDiskConverter;
import com.zchu.rxcache.stategy.CacheStrategy;
import com.zchu.rxcache.stategy.IStrategy;
import com.zchu.rxcache.utils.LogUtils;
import com.zchu.sample.ResourceTable;
import com.zchu.sample.ServerAPI;
import io.reactivex.rxjava3.annotations.NonNull;
import io.reactivex.rxjava3.core.Observer;
import io.reactivex.rxjava3.disposables.Disposable;
import io.reactivex.rxjava3.openharmony.schedulers.OpenHarmonySchedulers;
import io.reactivex.rxjava3.schedulers.Schedulers;
import ohos.aafwk.ability.AbilitySlice;
import ohos.aafwk.content.Intent;
import ohos.agp.components.Component;
import ohos.agp.components.Switch;
import ohos.agp.components.Text;
import okhttp3.OkHttpClient;
import retrofit2.Retrofit;
import retrofit2.adapter.rxjava3.RxJava3CallAdapterFactory;
import retrofit2.converter.scalars.ScalarsConverterFactory;

import java.io.File;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Locale;

public class MainAbilitySlice extends AbilitySlice implements Component.ClickedListener {

    private ServerAPI serverAPI;

    private Disposable mSubscription;

    private Text tvData;

    private Switch swIsAsync;

    private RxCache rxCache;

    @Override
    public void onStart(Intent intent) {
        super.onStart(intent);
        super.setUIContent(ResourceTable.Layout_ability_main);
        tvData = (Text) findComponentById(ResourceTable.Id_tv_data);
        swIsAsync = (Switch) findComponentById(ResourceTable.Id_sw_is_async);
        swIsAsync.setChecked(true);
        (findComponentById(ResourceTable.Id_btn_first_remote)).setClickedListener(this);
        (findComponentById(ResourceTable.Id_btn_first_cache)).setClickedListener(this);
        (findComponentById(ResourceTable.Id_btn_first_cache_timeout)).setClickedListener(this);
        (findComponentById(ResourceTable.Id_btn_only_remote)).setClickedListener(this);
        (findComponentById(ResourceTable.Id_btn_only_cache)).setClickedListener(this);
        (findComponentById(ResourceTable.Id_btn_cache_and_remote)).setClickedListener(this);
        (findComponentById(ResourceTable.Id_btn_none)).setClickedListener(this);
        (findComponentById(ResourceTable.Id_btn_clean_cache)).setClickedListener(this);
        (findComponentById(ResourceTable.Id_btn_load_cache)).setClickedListener(this);
        (findComponentById(ResourceTable.Id_btn_save_cache)).setClickedListener(this);

        serverAPI = new Retrofit.Builder().baseUrl(ServerAPI.BASE_URL)
            .addConverterFactory(ScalarsConverterFactory.create())
            .addCallAdapterFactory(RxJava3CallAdapterFactory.create())
            .client(new OkHttpClient.Builder().build())
            .build()
            .create(ServerAPI.class);
        rxCache = new RxCache.Builder().appVersion(2)
            .diskDir(new File(getCacheDir().getPath() + File.separator + "data-cache"))
            .diskConverter(new GsonDiskConverter())
            .diskMax(20 * 1024 * 1024)
            .memoryMax(2 * 1024 * 1024)
            .setDebug(true)
            .build();

    }

    @Override
    public void onActive() {
        super.onActive();
    }

    @Override
    public void onForeground(Intent intent) {
        super.onForeground(intent);
    }

    @Override
    public void onClick(Component component) {
        switch (component.getId()) {
            case ResourceTable.Id_btn_first_remote:
                if (swIsAsync.isChecked()) {
                    loadData(CacheStrategy.firstRemote());
                } else {
                    loadData(CacheStrategy.firstRemoteSync());
                }
                break;
            case ResourceTable.Id_btn_first_cache:
                if (swIsAsync.isChecked()) {
                    loadData(CacheStrategy.firstCache());
                } else {
                    loadData(CacheStrategy.firstCacheSync());
                }
                break;
            case ResourceTable.Id_btn_first_cache_timeout:
                if (swIsAsync.isChecked()) {
                    loadData(CacheStrategy.firstCacheTimeout(5000));
                } else {
                    loadData(CacheStrategy.firstCacheTimeoutSync(5000));
                }
                break;
            case ResourceTable.Id_btn_only_remote:
                if (swIsAsync.isChecked()) {
                    loadData(CacheStrategy.onlyRemote());
                } else {
                    loadData(CacheStrategy.onlyRemoteSync());
                }
                break;
            case ResourceTable.Id_btn_only_cache:
                loadData(CacheStrategy.onlyCache());
                break;
            case ResourceTable.Id_btn_cache_and_remote:
                if (swIsAsync.isChecked()) {
                    loadData(CacheStrategy.cacheAndRemote());
                } else {
                    loadData(CacheStrategy.cacheAndRemoteSync());
                }
                break;
            case ResourceTable.Id_btn_none:
                loadData(CacheStrategy.none());
                break;
            case ResourceTable.Id_btn_load_cache:
                RxCache.getDefault(this.getApplicationContext())
                    .load("custom_key",new TypeToken<String>(){}.getType())
                    .subscribe(new Observer<CacheResult<Object>>() {
                        @Override
                        public void onSubscribe(@NonNull Disposable disposable) {

                            mSubscription = disposable;
                        }

                        @Override
                        public void onNext(@NonNull CacheResult<Object> objectCacheResult) {
                            LogUtils.debug(objectCacheResult);
                            String format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss", Locale.getDefault()).format(
                                new Date(objectCacheResult.getTimestamp()));
                            tvData.setText("From Cache" + ResultFrom.ifFromCache(objectCacheResult.getFrom()) + "  Write Time：" + format + "\n " + objectCacheResult.getData());

                        }

                        @Override
                        public void onError(@NonNull Throwable e) {

                            tvData.setText(e.getMessage());
                        }

                        @Override
                        public void onComplete() {

                        }
                    });
                break;
            case ResourceTable.Id_btn_save_cache:
                RxCache.getDefault(this.getContext()).save("custom_key", "Test data").subscribe();
                tvData.setText("saved the cache");
                break;
            case ResourceTable.Id_btn_clean_cache:
                RxCache.getDefault(this.getContext()).clear().subscribe();
                tvData.setText("cleared the cache");
                break;
            default:
                break;
        }
    }

    private void loadData(IStrategy strategy) {
        if (mSubscription != null && !mSubscription.isDisposed()) {
            mSubscription.dispose();
        }
        long startTime = System.currentTimeMillis();

        serverAPI.fetchUsers()
            .compose(rxCache.transformObservable("custom_key", new TypeToken<String>() { }.getType(), strategy))
            .subscribeOn(Schedulers.io())
            .observeOn(OpenHarmonySchedulers.mainThread())
            .subscribe(new Observer<CacheResult<String>>() {
                @Override
                public void onSubscribe(@NonNull Disposable disposable) {

                    mSubscription = disposable;
                }

                @Override
                public void onNext(@NonNull CacheResult<String> stringCacheResult) {
                    LogUtils.debug(stringCacheResult);
                    if (ResultFrom.ifFromCache(stringCacheResult.getFrom())) {
                        String format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss", Locale.getDefault()).format(
                            new Date(stringCacheResult.getTimestamp()));
                        tvData.setText("Write time from cache：" + format + "\n " + stringCacheResult.getData());
                    } else {
                        tvData.setText(
                            "From the network：\n " + stringCacheResult.getData() + "\n Response Time：" + (System.currentTimeMillis()
                                - startTime) + "ms");
                    }
                }

                @Override
                public void onError(@NonNull Throwable e) {

                    tvData.setText(e.getMessage());
                }

                @Override
                public void onComplete() {

                }
            });

    }

}
